Tratamiento de Bases y analisis exploratorio inicial, Analisis de Seguros
Angela Chamorro
Vladimir Martin
Analitica 3
UdeA 2023-2
Antes de ejecutar, subir al entorno las 7 bases de datos suministradas
!pip install ydata_profiling
Requirement already satisfied: ydata_profiling in /usr/local/lib/python3.10/dist-packages (4.6.1) Requirement already satisfied: scipy<1.12,>=1.4.1 in /usr/local/lib/python3.10/dist-packages (from ydata_profiling) (1.11.3) Requirement already satisfied: pandas!=1.4.0,<2.1,>1.1 in /usr/local/lib/python3.10/dist-packages (from ydata_profiling) (1.5.3) Requirement already satisfied: matplotlib<=3.7.3,>=3.2 in /usr/local/lib/python3.10/dist-packages (from ydata_profiling) (3.7.1) Requirement already satisfied: pydantic>=2 in /usr/local/lib/python3.10/dist-packages (from ydata_profiling) (2.5.1) Requirement already satisfied: PyYAML<6.1,>=5.0.0 in /usr/local/lib/python3.10/dist-packages (from ydata_profiling) (6.0.1) Requirement already satisfied: jinja2<3.2,>=2.11.1 in /usr/local/lib/python3.10/dist-packages (from ydata_profiling) (3.1.2) Requirement already satisfied: visions[type_image_path]==0.7.5 in /usr/local/lib/python3.10/dist-packages (from ydata_profiling) (0.7.5) Requirement already satisfied: numpy<1.26,>=1.16.0 in /usr/local/lib/python3.10/dist-packages (from ydata_profiling) (1.23.5) Requirement already satisfied: htmlmin==0.1.12 in /usr/local/lib/python3.10/dist-packages (from ydata_profiling) (0.1.12) Requirement already satisfied: phik<0.13,>=0.11.1 in /usr/local/lib/python3.10/dist-packages (from ydata_profiling) (0.12.3) Requirement already satisfied: requests<3,>=2.24.0 in /usr/local/lib/python3.10/dist-packages (from ydata_profiling) (2.31.0) Requirement already satisfied: tqdm<5,>=4.48.2 in /usr/local/lib/python3.10/dist-packages (from ydata_profiling) (4.66.1) Requirement already satisfied: seaborn<0.13,>=0.10.1 in /usr/local/lib/python3.10/dist-packages (from ydata_profiling) (0.12.2) Requirement already satisfied: multimethod<2,>=1.4 in /usr/local/lib/python3.10/dist-packages (from ydata_profiling) (1.10) Requirement already satisfied: statsmodels<1,>=0.13.2 in /usr/local/lib/python3.10/dist-packages (from ydata_profiling) (0.14.0) Requirement already satisfied: typeguard<5,>=4.1.2 in /usr/local/lib/python3.10/dist-packages (from ydata_profiling) (4.1.5) Requirement already satisfied: imagehash==4.3.1 in /usr/local/lib/python3.10/dist-packages (from ydata_profiling) (4.3.1) Requirement already satisfied: wordcloud>=1.9.1 in /usr/local/lib/python3.10/dist-packages (from ydata_profiling) (1.9.2) Requirement already satisfied: dacite>=1.8 in /usr/local/lib/python3.10/dist-packages (from ydata_profiling) (1.8.1) Requirement already satisfied: numba<0.59.0,>=0.56.0 in /usr/local/lib/python3.10/dist-packages (from ydata_profiling) (0.58.1) Requirement already satisfied: PyWavelets in /usr/local/lib/python3.10/dist-packages (from imagehash==4.3.1->ydata_profiling) (1.4.1) Requirement already satisfied: pillow in /usr/local/lib/python3.10/dist-packages (from imagehash==4.3.1->ydata_profiling) (9.4.0) Requirement already satisfied: attrs>=19.3.0 in /usr/local/lib/python3.10/dist-packages (from visions[type_image_path]==0.7.5->ydata_profiling) (23.1.0) Requirement already satisfied: networkx>=2.4 in /usr/local/lib/python3.10/dist-packages (from visions[type_image_path]==0.7.5->ydata_profiling) (3.2.1) Requirement already satisfied: tangled-up-in-unicode>=0.0.4 in /usr/local/lib/python3.10/dist-packages (from visions[type_image_path]==0.7.5->ydata_profiling) (0.2.0) Requirement already satisfied: MarkupSafe>=2.0 in /usr/local/lib/python3.10/dist-packages (from jinja2<3.2,>=2.11.1->ydata_profiling) (2.1.3) Requirement already satisfied: contourpy>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib<=3.7.3,>=3.2->ydata_profiling) (1.2.0) Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.10/dist-packages (from matplotlib<=3.7.3,>=3.2->ydata_profiling) (0.12.1) Requirement already satisfied: fonttools>=4.22.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib<=3.7.3,>=3.2->ydata_profiling) (4.44.3) Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib<=3.7.3,>=3.2->ydata_profiling) (1.4.5) Requirement already satisfied: packaging>=20.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib<=3.7.3,>=3.2->ydata_profiling) (23.2) Requirement already satisfied: pyparsing>=2.3.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib<=3.7.3,>=3.2->ydata_profiling) (3.1.1) Requirement already satisfied: python-dateutil>=2.7 in /usr/local/lib/python3.10/dist-packages (from matplotlib<=3.7.3,>=3.2->ydata_profiling) (2.8.2) Requirement already satisfied: llvmlite<0.42,>=0.41.0dev0 in /usr/local/lib/python3.10/dist-packages (from numba<0.59.0,>=0.56.0->ydata_profiling) (0.41.1) Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.10/dist-packages (from pandas!=1.4.0,<2.1,>1.1->ydata_profiling) (2023.3.post1) Requirement already satisfied: joblib>=0.14.1 in /usr/local/lib/python3.10/dist-packages (from phik<0.13,>=0.11.1->ydata_profiling) (1.3.2) Requirement already satisfied: annotated-types>=0.4.0 in /usr/local/lib/python3.10/dist-packages (from pydantic>=2->ydata_profiling) (0.6.0) Requirement already satisfied: pydantic-core==2.14.3 in /usr/local/lib/python3.10/dist-packages (from pydantic>=2->ydata_profiling) (2.14.3) Requirement already satisfied: typing-extensions>=4.6.1 in /usr/local/lib/python3.10/dist-packages (from pydantic>=2->ydata_profiling) (4.7.1) Requirement already satisfied: charset-normalizer<4,>=2 in /usr/local/lib/python3.10/dist-packages (from requests<3,>=2.24.0->ydata_profiling) (3.3.2) Requirement already satisfied: idna<4,>=2.5 in /usr/local/lib/python3.10/dist-packages (from requests<3,>=2.24.0->ydata_profiling) (3.4) Requirement already satisfied: urllib3<3,>=1.21.1 in /usr/local/lib/python3.10/dist-packages (from requests<3,>=2.24.0->ydata_profiling) (2.0.7) Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.10/dist-packages (from requests<3,>=2.24.0->ydata_profiling) (2023.7.22) Requirement already satisfied: patsy>=0.5.2 in /usr/local/lib/python3.10/dist-packages (from statsmodels<1,>=0.13.2->ydata_profiling) (0.5.3) Requirement already satisfied: six in /usr/local/lib/python3.10/dist-packages (from patsy>=0.5.2->statsmodels<1,>=0.13.2->ydata_profiling) (1.16.0)
!pip install typing_extensions==4.7.1 --upgrade
Requirement already satisfied: typing_extensions==4.7.1 in /usr/local/lib/python3.10/dist-packages (4.7.1)
from ydata_profiling import ProfileReport
#IMPORTAR PAQUETES
import numpy as np
import pandas as pd
import datetime
from matplotlib import pyplot as plt
import seaborn as sns
from sklearn.preprocessing import StandardScaler
#funcion para convertir fecha excel a date_time
#to_datetime tiene una base en 01-01-1970(que equivale a 25569), entonces al restar, sacamos los dias desde 1970 a la fecha respectiva
#despues lo multiplicamos por el numero de segundos por dia (86400) y esto se lo damos a to_datetime especificando que esta en segundos
def exceldate(n):
seconds = (n - 25569) * 86400.0
return pd.to_datetime(seconds,unit="s")
def reemplazar_numerico(valor):
return 'Si' if pd.notna(valor) and isinstance(valor, (int, float)) else "No"
#base de datos de Utilizaciones medicas
df_utl = pd.read_csv("BD_UtilizacionesMedicas.csv", sep=";")
#base de datos de datos Socio Demograficas
df_scd = pd.read_csv("BD_SocioDemograficas.csv", sep=";")
#base de datos asegurados expuestos
df_aseg = pd.read_csv("BD_Asegurados_Expuestos.csv", sep=";")
#base de datos diccionario Diagnostico
df_diag = pd.read_csv("/content/BD_Diagnostico.csv", sep=";")
#base de datos diccionario genero
df_gen = pd.read_csv("/content/BD_Genero.csv", sep=";")
#base de datos diccionario regional
df_reg = pd.read_csv("/content/BD_Regional.csv", sep=";")
#base de datos diccionario reclamaciones
df_recl = pd.read_csv("/content/BD_Reclamaciones.csv", sep=";")
<ipython-input-23-aa08c0254274>:4: DtypeWarning: Columns (3) have mixed types. Specify dtype option on import or set low_memory=False.
df_scd = pd.read_csv("BD_SocioDemograficas.csv", sep=";")
#visualizamos la bd Socio Demograficas
df_scd.head(3)
| Afiliado_Id | Sexo_Cd | FechaNacimiento | Regional | CANCER | EPOC | DIABETES | HIPERTENSION | ENF_CARDIOVASCULAR | |
|---|---|---|---|---|---|---|---|---|---|
| 0 | 738288 | 2 | 28072 | 40 | 0 | 0 | 0 | 0 | 0 |
| 1 | 738294 | 2 | 23392 | 50 | 0 | 0 | 0 | 0 | 0 |
| 2 | 738303 | 1 | 27177 | 10 | 0 | 0 | 0 | 0 | 0 |
print("Esta base tiene",df_scd.shape[0],"Registros", "que corresponden a",df_scd['Afiliado_Id'].nunique(), "afiliados. ")
#la base deberia tener todos los valores unicos,pero existen 13 registros repetidos de afiliados.
Esta base tiene 225776 Registros que corresponden a 225763 afiliados.
#ver registros repetidos
df_scd[df_scd.duplicated(subset="Afiliado_Id",keep=False)].head(4)
| Afiliado_Id | Sexo_Cd | FechaNacimiento | Regional | CANCER | EPOC | DIABETES | HIPERTENSION | ENF_CARDIOVASCULAR | |
|---|---|---|---|---|---|---|---|---|---|
| 142499 | 31730923 | 1 | 41671 | 10 | 0 | 0 | 0 | 0 | 0 |
| 142500 | 31730923 | 1 | 41671 | 40 | 0 | 0 | 0 | 0 | 0 |
| 157276 | 36189021 | 2 | 41427 | 30 | 0 | 0 | 0 | 0 | 0 |
| 157277 | 36189021 | 2 | 41427 | 40 | 0 | 0 | 0 | 0 | 0 |
-Nos damos cuenta que se repite el registro por cliente porque se hace el ingreso de otra afiliacion en otra regional.
#se decide dejar para cada afiliado con registro duplicado, la ultima regional asignada segun el orden en la base de datos.
elim=df_scd[df_scd.duplicated(subset="Afiliado_Id",keep="first")]
df_scd=df_scd.drop(elim.index.tolist())
print("Se deja unicamente el ultimo registro por afiliado, se obtiene entonces que: ")
print("Esta base tiene",df_scd.shape[0],"Registros", "que corresponden a",df_scd['Afiliado_Id'].nunique(), "afiliados")
Se deja unicamente el ultimo registro por afiliado, se obtiene entonces que: Esta base tiene 225763 Registros que corresponden a 225763 afiliados
#visualizamo la bd de Utilizaciones medicas
df_utl.head(3)
| Fecha_Reclamacion | Afiliado_Id | Reclamacion_Cd | Diagnostico_Codigo | Numero_Utilizaciones | Valor_Utilizaciones | |
|---|---|---|---|---|---|---|
| 0 | 43766 | 2668445 | R10 | 9 | 1 | 46500 |
| 1 | 43738 | 4370072 | R15 | 9 | 2 | 42408 |
| 2 | 43766 | 7567894 | R14 | N649 | 1 | 139376 |
print("Esta base tiene",df_utl.shape[0],"Registros", "que corresponden a",df_utl['Afiliado_Id'].nunique(), "afiliados")
Esta base tiene 800232 Registros que corresponden a 161748 afiliados
#visualizamos la bd asegurados expuestos
df_aseg
| Asegurado_Id | Poliza_Id | FECHA_INICIO | FECHA_CANCELACION | FECHA_FIN | |
|---|---|---|---|---|---|
| 0 | 1213170 | 113307876 | 43709 | NaN | 43814 |
| 1 | 22248110 | 195410143 | 43709 | 43830.0 | 43830 |
| 2 | 7212095 | 192799506 | 43709 | 43830.0 | 43830 |
| 3 | 23743715 | 145500123 | 43709 | 43830.0 | 43830 |
| 4 | 57822199 | 175415440 | 43709 | 43830.0 | 43830 |
| ... | ... | ... | ... | ... | ... |
| 231515 | 1475469 | 129009780 | 43709 | NaN | 43830 |
| 231516 | 5867040 | 122473992 | 43709 | NaN | 43830 |
| 231517 | 17992105 | 160393703 | 43709 | NaN | 43830 |
| 231518 | 48708455 | 156289019 | 43709 | NaN | 43830 |
| 231519 | 30913881 | 201345473 | 43709 | 43830.0 | 43830 |
231520 rows × 5 columns
#vemos que algunos usuarios cancelan la poliza despues del fin de la misma.
pp=df_aseg[df_aseg["FECHA_CANCELACION"].notna()]
pp[pp["FECHA_CANCELACION"]!=pp["FECHA_FIN"]].head(3)
| Asegurado_Id | Poliza_Id | FECHA_INICIO | FECHA_CANCELACION | FECHA_FIN | |
|---|---|---|---|---|---|
| 9234 | 2461341 | 123364068 | 43709 | 43825.0 | 43770 |
| 10394 | 45012207 | 197936354 | 43709 | 43784.0 | 43768 |
| 18248 | 30662011 | 201582576 | 43747 | 43790.0 | 43777 |
vemos que algunos usuarios cancelan la poliza despues del fin de la misma.
#vemos que de ella podemos extraer dos variables utiles para el modelo, el tiempo de duracion de la poliza y si la poliza fue cancelada o no.
#convertimos columnas a formato fecha
df_aseg["FECHA_INICIO"]=exceldate(df_aseg["FECHA_INICIO"])
df_aseg["FECHA_FIN"]=exceldate(df_aseg["FECHA_FIN"])
#creamos la columna duracion poliza
df_aseg["DUR_POL"]=(df_aseg['FECHA_FIN']-df_aseg["FECHA_INICIO"]).astype("<m8[D]")+1 #se le suma 1 ya que se cuenta el dia de inicio desde las 00:00 entonces se se acaba la poliza el mismo dia, la duracion seria 1 dia, no 0.
#Creamos la columna cancelacion
df_aseg["CANCEL"]=df_aseg["FECHA_CANCELACION"].apply(reemplazar_numerico)
#Eliminamos la columna FECHA_CANCELACION
df_aseg=df_aseg.drop("FECHA_CANCELACION",axis=1)
#Renombramos la columna asegurado_id
df_aseg.rename(columns={"Asegurado_Id":"Afiliado_Id"},inplace=True)
print("base de datos con el tiempo de duracion de la poliza y si la poliza fue cancelada o no")
df_aseg.head(3)
base de datos con el tiempo de duracion de la poliza y si la poliza fue cancelada o no
| Afiliado_Id | Poliza_Id | FECHA_INICIO | FECHA_FIN | DUR_POL | CANCEL | |
|---|---|---|---|---|---|---|
| 0 | 1213170 | 113307876 | 2019-09-01 | 2019-12-15 | 106.0 | No |
| 1 | 22248110 | 195410143 | 2019-09-01 | 2019-12-31 | 122.0 | Si |
| 2 | 7212095 | 192799506 | 2019-09-01 | 2019-12-31 | 122.0 | Si |
#se analiza si hay mas de 1 poliza por asegurado
print("Esta base tiene",df_aseg.shape[0],"polizas", "que corresponden a",df_aseg['Afiliado_Id'].nunique(), "afiliados")
Esta base tiene 231520 polizas que corresponden a 225763 afiliados
existen afiliados con mas de 1 poliza
#existen clientes con polizas seguidas, otros con polizas sepradas, y otros con varias polizas al tiempo.
df_aseg[df_aseg.duplicated(subset="Afiliado_Id",keep=False)].sort_values(by='Afiliado_Id', ascending=False)
| Afiliado_Id | Poliza_Id | FECHA_INICIO | FECHA_FIN | DUR_POL | CANCEL | |
|---|---|---|---|---|---|---|
| 221985 | 60975491 | 191752551 | 2019-09-01 | 2019-11-28 | 89.0 | Si |
| 76640 | 60975491 | 203954951 | 2019-11-30 | 2019-12-31 | 32.0 | No |
| 4999 | 60750733 | 126260749 | 2019-09-01 | 2019-12-31 | 122.0 | No |
| 212584 | 60750733 | 126266526 | 2019-09-01 | 2019-12-31 | 122.0 | No |
| 38440 | 60645652 | 203353878 | 2019-12-01 | 2019-12-31 | 31.0 | No |
| ... | ... | ... | ... | ... | ... | ... |
| 92053 | 738886 | 91476427 | 2019-09-01 | 2019-10-30 | 60.0 | Si |
| 14897 | 738886 | 201222934 | 2019-10-30 | 2019-10-31 | 2.0 | Si |
| 22270 | 738886 | 202863837 | 2019-10-31 | 2019-12-31 | 62.0 | Si |
| 114247 | 738443 | 203732930 | 2019-11-12 | 2019-12-31 | 50.0 | No |
| 127234 | 738443 | 119397955 | 2019-09-01 | 2019-11-12 | 73.0 | Si |
11166 rows × 6 columns
De los clientes con varias polizas, se pueden ver que unos las renuevan se forma inmediata, otros con un tiempo de separacion y otros tienen varias polizas al tiempo, esto ultimo debido posiblemente a que estan a nombre de un solo titular, pero los beneficiarios pueden ser diferentes
Analisis de cancelaciones
Si genera error, dar click en la generacion de graficos de la tabla anterior, despues si ejecutar las lineas de codigo siguientes
import seaborn as sns
_df_3.groupby('CANCEL').size().plot(kind='barh', color=sns.palettes.mpl_palette('Dark2'),title='Cancelaciones')
plt.gca().spines[['top', 'right',]].set_visible(False)
print("Porcentajes de cancelaciones")
((df_aseg['CANCEL'].value_counts()/len(df_aseg))*100).round(2)
Porcentajes de cancelaciones
No 54.73 Si 45.27 Name: CANCEL, dtype: float64
from matplotlib import pyplot as plt
_df_2['DUR_POL'].plot(kind='hist', bins=20, title='Duracion Poliza (Dias)')
plt.gca().spines[['top', 'right',]].set_visible(False)
#se decide promediar los dias de duracion de las polizas para tener un promedio de dias asegurado por cliente.
df_aseg_prom=df_aseg.groupby("Afiliado_Id")["DUR_POL"].mean().reset_index()
#se cuenta despues, para cada duracion, el numero de usuarios con esta duracion
pd.DataFrame(df_aseg_prom['DUR_POL'].value_counts().reset_index()).head(5).rename(columns={'index': 'Dias_Promedio',"DUR_POL":"Usuarios"}).sort_values(by='Dias_Promedio', ascending=False)
| Dias_Promedio | Usuarios | |
|---|---|---|
| 0 | 122.0 | 199890 |
| 4 | 92.0 | 1303 |
| 1 | 61.5 | 3130 |
| 3 | 31.0 | 1407 |
| 2 | 1.0 | 1884 |
df_aseg_prom['DUR_POL'].plot(kind='hist', bins=20, title='Duracion promedio de poliza en dias')
plt.gca().spines[['top', 'right',]].set_visible(False)
print("Un ",round((199890/len(df_aseg_prom))*100,2),"% de los usuarios, tienen polizas con una duracion de 122 dias, o 4 meses aprox")
Un 88.54 % de los usuarios, tienen polizas con una duracion de 122 dias, o 4 meses aprox
#Unimos las bd de utilizaciones Medicas y socio demograficos desde el Afiliado_Id.
df_completa = pd.merge(df_utl, df_scd, on='Afiliado_Id', how='left')
df_completa.head(3)
| Fecha_Reclamacion | Afiliado_Id | Reclamacion_Cd | Diagnostico_Codigo | Numero_Utilizaciones | Valor_Utilizaciones | Sexo_Cd | FechaNacimiento | Regional | CANCER | EPOC | DIABETES | HIPERTENSION | ENF_CARDIOVASCULAR | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 43766 | 2668445 | R10 | 9 | 1 | 46500 | 1.0 | 22999.0 | 50 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 |
| 1 | 43738 | 4370072 | R15 | 9 | 2 | 42408 | 1.0 | 24071.0 | 10 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 2 | 43766 | 7567894 | R14 | N649 | 1 | 139376 | 1.0 | 28985.0 | 40 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
#puede haber varios registros por afiliado, es decir, afiliados con varias reclamaciones.
print("Estas son las reclamaciones para el afiliado ID=2668445\n")
df_completa.loc[df_completa['Afiliado_Id'] == 2668445]
Estas son las reclamaciones para el afiliado ID=2668445
| Fecha_Reclamacion | Afiliado_Id | Reclamacion_Cd | Diagnostico_Codigo | Numero_Utilizaciones | Valor_Utilizaciones | Sexo_Cd | FechaNacimiento | Regional | CANCER | EPOC | DIABETES | HIPERTENSION | ENF_CARDIOVASCULAR | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 43766 | 2668445 | R10 | 9 | 1 | 46500 | 1.0 | 22999.0 | 50 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 |
| 428138 | 43739 | 2668445 | R10 | 9 | 1 | 55676 | 1.0 | 22999.0 | 50 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 |
| 479193 | 43719 | 2668445 | R10 | 9 | 2 | 157852 | 1.0 | 22999.0 | 50 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 |
| 625599 | 43728 | 2668445 | R18 | 9 | 6 | 76455 | 1.0 | 22999.0 | 50 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 |
#Dimension de la base
print('La dimensión de los datos es:', df_completa.shape, 'con', df_completa.shape[0], 'registros y ', df_completa.shape[1], 'columnas')
#valores nulos
print("\n ###valores nulos###\n")
df_completa.isnull().sum()
La dimensión de los datos es: (800232, 14) con 800232 registros y 14 columnas
###valores nulos###
Fecha_Reclamacion 0 Afiliado_Id 0 Reclamacion_Cd 0 Diagnostico_Codigo 0 Numero_Utilizaciones 0 Valor_Utilizaciones 0 Sexo_Cd 3052 FechaNacimiento 3052 Regional 3052 CANCER 3052 EPOC 3052 DIABETES 3052 HIPERTENSION 3052 ENF_CARDIOVASCULAR 3052 dtype: int64
#buscamos los registros con valores nulos(los cuales corresponden a las variables de la base de datos de socio demograficas)
df_completa[df_completa['Sexo_Cd'].isnull()].head(3)
| Fecha_Reclamacion | Afiliado_Id | Reclamacion_Cd | Diagnostico_Codigo | Numero_Utilizaciones | Valor_Utilizaciones | Sexo_Cd | FechaNacimiento | Regional | CANCER | EPOC | DIABETES | HIPERTENSION | ENF_CARDIOVASCULAR | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 407 | 43337 | 40522640 | R8 | 9 | 1 | 46664 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 608 | 43697 | 9871226 | R22 | I500 | 1 | 322148 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 647 | 43699 | 48636409 | R10 | 9 | 1 | 85312 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
#tomamos un valor de ejemplo, para buscarlo en la base de datos de sociodemograficas y descartar un error en el merge
df_scd.loc[df_scd['Afiliado_Id'] == 40522640]
#se puede ver que el origen de estos 3052 valores nulos es debido a que son clientes que utilizaron los servicios, pero no se encuentran en la base de datos demograficos.
print("De un total de ",df_completa.shape[0] ,"registros y ",df_completa['Afiliado_Id'].nunique(),"clientes, " ,df_completa["Sexo_Cd"].isnull().sum() ," registros no tienen datos demograficos. \nEsto corresponde a ", df_completa[df_completa['Sexo_Cd'].isnull()]["Afiliado_Id"].unique().shape[0],"clientes,un ",round((df_completa[df_completa['Sexo_Cd'].isnull()]["Afiliado_Id"].unique().shape[0])/(df_completa.shape[0])*100,2),"%,que al no tener datos completos, seran eliminados de la base de datos")
elim2=df_completa[df_completa["Sexo_Cd"].isnull()]
df_completa=df_completa.drop(elim2.index.tolist())
De un total de 800232 registros y 161748 clientes, 3052 registros no tienen datos demograficos. Esto corresponde a 1741 clientes,un 0.22 %,que al no tener datos completos, seran eliminados de la base de datos
#Debido a que nos interesa predecir las utilizaciones y los costos de estas teniendo en cuenta el tipo de diagnostico, eliminamos las filas con diagnostico pendiente o sin diagnostico
df_completa=df_completa[df_completa["Diagnostico_Codigo"]!= "9"].reset_index(drop=True) #Diagnositco pendiente
df_compleya=df_completa[df_completa["Diagnostico_Codigo"]!= "0"].reset_index(drop=True) #Diagnostico pendiente
df_completa=df_completa[df_completa["Diagnostico_Codigo"]!= "-1"].reset_index(drop=True) #sin diagnositco
#pasamos la columna de Fecha de Nacimiento a formato fecha
df_completa["FechaNacimiento"]=exceldate(df_completa["FechaNacimiento"])
#pasamos la columna de Fecha Reclamación a formato fecha
df_completa["Fecha_Reclamacion"]=exceldate(df_completa["Fecha_Reclamacion"])
#creamos columna edad
df_completa["Edad"]=(df_completa['Fecha_Reclamacion']-df_completa["FechaNacimiento"]).astype("<m8[Y]")
df_completa.head(5)
| Fecha_Reclamacion | Afiliado_Id | Reclamacion_Cd | Diagnostico_Codigo | Numero_Utilizaciones | Valor_Utilizaciones | Sexo_Cd | FechaNacimiento | Regional | CANCER | EPOC | DIABETES | HIPERTENSION | ENF_CARDIOVASCULAR | Edad | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 2019-10-28 | 7567894 | R14 | N649 | 1 | 139376 | 1.0 | 1979-05-10 | 40 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 40.0 |
| 1 | 2019-12-23 | 12170310 | R14 | R529 | 1 | 135179 | 1.0 | 1979-04-14 | 40 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 40.0 |
| 2 | 2019-12-09 | 4512914 | R14 | Z108 | 1 | 61854 | 1.0 | 1952-10-26 | 50 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 67.0 |
| 3 | 2019-08-17 | 3212499 | R14 | R072 | 1 | 182900 | 2.0 | 1965-10-03 | 50 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 53.0 |
| 4 | 2019-12-10 | 9055837 | R25 | S934 | 1 | 122053 | 1.0 | 1972-04-29 | 50 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 47.0 |
#dimension de la base
print('La dimensión de los datos es:', df_completa.shape, 'con', df_completa.shape[0], 'registros y ', df_completa.shape[1], 'columnas')
#valores nulos
print("\n ###valores nulos###\n")
df_completa.isnull().sum()
La dimensión de los datos es: (100678, 15) con 100678 registros y 15 columnas
###valores nulos###
Fecha_Reclamacion 0 Afiliado_Id 0 Reclamacion_Cd 0 Diagnostico_Codigo 0 Numero_Utilizaciones 0 Valor_Utilizaciones 0 Sexo_Cd 0 FechaNacimiento 0 Regional 0 CANCER 0 EPOC 0 DIABETES 0 HIPERTENSION 0 ENF_CARDIOVASCULAR 0 Edad 0 dtype: int64
#revisamos el tipo de datos que tenemos en cada variable
df_completa.dtypes
Fecha_Reclamacion datetime64[ns] Afiliado_Id int64 Reclamacion_Cd object Diagnostico_Codigo object Numero_Utilizaciones int64 Valor_Utilizaciones int64 Sexo_Cd float64 FechaNacimiento datetime64[ns] Regional object CANCER float64 EPOC float64 DIABETES float64 HIPERTENSION float64 ENF_CARDIOVASCULAR float64 Edad float64 dtype: object
df_completa_1=df_completa.copy()
#ya que los modelos no son muy buenos interpretando valores de fecha, extraemos de las variables que puedan aportar al modelo
#podemos extraer el mes de la reclamacion, de nacimiento y el año de reclamacion, el año de nacimiento es equivalente a la edad.
df_completa_1["mes_rec"]=df_completa_1["Fecha_Reclamacion"].dt.month
df_completa_1["año_rec"]=df_completa_1["Fecha_Reclamacion"].dt.year
df_completa_1["mes_nac"]=df_completa_1["FechaNacimiento"].dt.month
df_completa_1.head(2)
| Fecha_Reclamacion | Afiliado_Id | Reclamacion_Cd | Diagnostico_Codigo | Numero_Utilizaciones | Valor_Utilizaciones | Sexo_Cd | FechaNacimiento | Regional | CANCER | EPOC | DIABETES | HIPERTENSION | ENF_CARDIOVASCULAR | Edad | mes_rec | año_rec | mes_nac | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 2019-10-28 | 7567894 | R14 | N649 | 1 | 139376 | 1.0 | 1979-05-10 | 40 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 40.0 | 10 | 2019 | 5 |
| 1 | 2019-12-23 | 12170310 | R14 | R529 | 1 | 135179 | 1.0 | 1979-04-14 | 40 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 40.0 | 12 | 2019 | 4 |
#hacemos un analisis general
df_completa_1.describe()
| Afiliado_Id | Numero_Utilizaciones | Valor_Utilizaciones | Sexo_Cd | CANCER | EPOC | DIABETES | HIPERTENSION | ENF_CARDIOVASCULAR | Edad | mes_rec | año_rec | mes_nac | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| count | 1.006780e+05 | 100678.000000 | 1.006780e+05 | 100678.000000 | 100678.000000 | 100678.000000 | 100678.000000 | 100678.000000 | 100678.000000 | 100678.000000 | 100678.000000 | 100678.000000 | 100678.000000 |
| mean | 1.750154e+07 | 1.024921 | 1.328091e+06 | 1.379894 | 0.075021 | 0.018852 | 0.084030 | 0.193319 | 0.014879 | 42.547627 | 9.416764 | 2018.995133 | 6.579541 |
| std | 1.531496e+07 | 0.166663 | 5.745133e+06 | 0.485363 | 0.263427 | 0.136004 | 0.277435 | 0.394903 | 0.121070 | 20.169827 | 1.828264 | 0.078703 | 3.471375 |
| min | 7.383180e+05 | 1.000000 | 3.790000e+02 | 1.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | -2.000000 | 1.000000 | 2015.000000 | 1.000000 |
| 25% | 4.734831e+06 | 1.000000 | 6.470200e+04 | 1.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 31.000000 | 9.000000 | 2019.000000 | 4.000000 |
| 50% | 1.205593e+07 | 1.000000 | 1.482540e+05 | 1.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 42.000000 | 10.000000 | 2019.000000 | 7.000000 |
| 75% | 2.768288e+07 | 1.000000 | 6.212400e+05 | 2.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 57.000000 | 11.000000 | 2019.000000 | 10.000000 |
| max | 6.115209e+07 | 5.000000 | 5.410007e+08 | 2.000000 | 1.000000 | 1.000000 | 1.000000 | 1.000000 | 1.000000 | 102.000000 | 12.000000 | 2019.000000 | 12.000000 |
#Llama la atencion la variable edad, que tiene un valor minimo negativo, al ser una variable determinante para el modelo y los seguros, se analiza a profundidad.
df_edad=pd.DataFrame(df_completa_1["Edad"].value_counts()).reset_index().rename(columns={'index': 'Edad',"Edad":"Reclamaciones"}).sort_values(by='Edad')
df_edad
| Edad | Reclamaciones | |
|---|---|---|
| 104 | -2.0 | 1 |
| 75 | -1.0 | 436 |
| 21 | 0.0 | 1647 |
| 46 | 1.0 | 925 |
| 44 | 2.0 | 976 |
| ... | ... | ... |
| 99 | 98.0 | 9 |
| 102 | 99.0 | 4 |
| 101 | 100.0 | 5 |
| 103 | 101.0 | 3 |
| 100 | 102.0 | 6 |
105 rows × 2 columns
from matplotlib import pyplot as plt
df_edad.plot(kind='scatter', x='Edad', y='Reclamaciones', s=32, alpha=.8, title='Reclamaciones por edad')
plt.gca().spines[['top', 'right',]].set_visible(False)
#se comprueban edades negativas y edades con un valor de 0.
#se validaran estos numeros con una columna de edad_2, calculada apartir de la fecha de nacimiento y la fecha de la reclamacion.
df_completa_1["dias_edad"]=(df_completa_1['Fecha_Reclamacion']-df_completa_1["FechaNacimiento"]).dt.days#.astype("<m8[m]")
df_completa_1["Edad_2"]=df_completa_1["dias_edad"]/365.2425
la variable Edad_2 da como resultado los años en decimas de año, por loq ue algunos valores antes 0, ahora son calores menores a 1, que significan menos de 365 dias/12 meses de edad
#ahora vamos a comprobar las condiciones solo con las variables involucradas en la edad
diag_edad_neg=df_completa_1[["Fecha_Reclamacion","FechaNacimiento","Edad","Edad_2","dias_edad","Diagnostico_Codigo"]][df_completa_1["Edad"]<=-1]
#vamos a remplazar los valores del diagnostico, para encontrar alguna relacion
remp1=dict(zip(df_diag['Diagnostico_Codigo'],df_diag["Diagnostico_Desc"]))
diag_edad_neg["Diagnostico_Codigo"]=diag_edad_neg["Diagnostico_Codigo"].replace(remp1)
pd.set_option('display.max_colwidth', None)
diag_edad_neg
| Fecha_Reclamacion | FechaNacimiento | Edad | Edad_2 | dias_edad | Diagnostico_Codigo | |
|---|---|---|---|---|---|---|
| 41 | 2019-09-06 | 2019-09-20 | -1.0 | -0.038331 | -14 | CARCINOMA IN SITU DE LA GLÁNDULA TIROIDES Y DE OTRAS GLÁNDULAS ENDOCRINAS |
| 593 | 2019-09-25 | 2019-10-19 | -1.0 | -0.065710 | -24 | DIFICULTAD RESPIRATORIA DEL RECIÉN NACIDO, NO ESPECIFICADA |
| 726 | 2019-10-30 | 2019-11-04 | -1.0 | -0.013690 | -5 | EXAMEN DE OÍDOS Y DE LA AUDICIÓN |
| 863 | 2019-11-07 | 2019-11-29 | -1.0 | -0.060234 | -22 | SÍNDROME DE DIFICULTAD RESPIRATORIA DEL RECIÉN NACIDO |
| 1177 | 2019-10-21 | 2019-10-25 | -1.0 | -0.010952 | -4 | BRONQUIOLITIS AGUDA, NO ESPECIFICADA |
| ... | ... | ... | ... | ... | ... | ... |
| 98729 | 2019-09-30 | 2019-10-21 | -1.0 | -0.057496 | -21 | DIFICULTAD RESPIRATORIA DEL RECIÉN NACIDO, NO ESPECIFICADA |
| 99515 | 2019-04-26 | 2019-05-05 | -1.0 | -0.024641 | -9 | OTROS CONTROLES GENERALES DE SALUD DE RUTINA DE OTRAS SUBPOBLACIONES DEFINIDAS |
| 99628 | 2019-11-26 | 2019-12-10 | -1.0 | -0.038331 | -14 | CONVULSIONES DEL RECIÉN NACIDO |
| 99790 | 2019-09-28 | 2019-10-22 | -1.0 | -0.065710 | -24 | SEPSIS BACTERIANA DEL RECIÉN NACIDO, NO ESPECIFICADA |
| 100006 | 2019-12-08 | 2019-12-20 | -1.0 | -0.032855 | -12 | BRONQUIOLITIS AGUDA, NO ESPECIFICADA |
437 rows × 6 columns
Vemos como comun diagnosticos relacionados con recien nacido, asi que se va a suponer que la fecha de reclamacion es menor a la de nacimiento, porque la madre ingreso dias antes del nacimiento por algun sintoma o patologia de ella, o del feto/recien nacido, por lo que la edad negativa se remplazara por 1 dia de nacido o
#se remplazan los valores y ademas se elimina registro con edad=-2 ya que no hya ingunindicio de que sea un recien nacido y se considerara como un atipico
df_completa_1.loc[df_completa_1["Edad_2"]<0,"Edad_2"]=1/365.2425
df_completa_1=df_completa_1.drop(df_completa_1[df_completa_1["Edad"]==-2].index)
#ahora analizamos los valores con edades de 0
df_completa_1[df_completa_1["Edad_2"]==0]
#se comprueba que nacen el mismo dia del registro de la reclamacion, su valor sera remplazado por edad de 1 dia.
df_completa_1.loc[df_completa_1["Edad_2"]==0,"Edad_2"]=1/365.2425
pd.DataFrame(df_completa_1["Edad_2"].value_counts()).reset_index().rename(columns={'index': 'Edad',"Edad_2":"Reclamaciones"}).sort_values(by='Edad')
| Edad | Reclamaciones | |
|---|---|---|
| 0 | 0.002738 | 462 |
| 194 | 0.005476 | 12 |
| 1593 | 0.008214 | 8 |
| 698 | 0.010952 | 10 |
| 13 | 0.013690 | 16 |
| ... | ... | ... |
| 22830 | 102.091076 | 1 |
| 22155 | 102.293682 | 1 |
| 28029 | 102.299157 | 1 |
| 26688 | 102.315585 | 1 |
| 21737 | 102.436053 | 1 |
28129 rows × 2 columns
#se elimina la antigua variable Edad y se limitan los decimales de la variable edad_2 a dos decimales
df_completa_2 = df_completa_1.drop(columns=['Edad','dias_edad'])
df_completa_2 = df_completa_2.rename(columns={'Edad_2': 'Edad'})
df_completa_2['Edad'] = df_completa_2['Edad'].round(2)
df_completa_2.head(2)
| Fecha_Reclamacion | Afiliado_Id | Reclamacion_Cd | Diagnostico_Codigo | Numero_Utilizaciones | Valor_Utilizaciones | Sexo_Cd | FechaNacimiento | Regional | CANCER | EPOC | DIABETES | HIPERTENSION | ENF_CARDIOVASCULAR | mes_rec | año_rec | mes_nac | Edad | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 2019-10-28 | 7567894 | R14 | N649 | 1 | 139376 | 1.0 | 1979-05-10 | 40 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 10 | 2019 | 5 | 40.47 |
| 1 | 2019-12-23 | 12170310 | R14 | R529 | 1 | 135179 | 1.0 | 1979-04-14 | 40 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 12 | 2019 | 4 | 40.69 |
df_completa_2.info()
<class 'pandas.core.frame.DataFrame'> Int64Index: 100677 entries, 0 to 100677 Data columns (total 18 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Fecha_Reclamacion 100677 non-null datetime64[ns] 1 Afiliado_Id 100677 non-null int64 2 Reclamacion_Cd 100677 non-null object 3 Diagnostico_Codigo 100677 non-null object 4 Numero_Utilizaciones 100677 non-null int64 5 Valor_Utilizaciones 100677 non-null int64 6 Sexo_Cd 100677 non-null float64 7 FechaNacimiento 100677 non-null datetime64[ns] 8 Regional 100677 non-null object 9 CANCER 100677 non-null float64 10 EPOC 100677 non-null float64 11 DIABETES 100677 non-null float64 12 HIPERTENSION 100677 non-null float64 13 ENF_CARDIOVASCULAR 100677 non-null float64 14 mes_rec 100677 non-null int64 15 año_rec 100677 non-null int64 16 mes_nac 100677 non-null int64 17 Edad 100677 non-null float64 dtypes: datetime64[ns](2), float64(7), int64(6), object(3) memory usage: 14.6+ MB
df_completa_2["Regional"]=df_completa_2["Regional"].astype("int")
print("Regional: \n",df_completa_2["Regional"].value_counts())
Regional: 50 63841 40 15224 20 10520 10 9116 30 1972 -1 4 Name: Regional, dtype: int64
#eliminamos registro sin informacion regional
df_completa_2 = df_completa_2.drop(df_completa_2[df_completa_2["Regional"] == -1].index)
print("Regional: \n",df_completa_2["Regional"].value_counts())
Regional: 50 63841 40 15224 20 10520 10 9116 30 1972 Name: Regional, dtype: int64
df_completa_3=df_completa_2.copy()
#volvemos a crear columna edad para el analisis
df_completa_3["Edad"]=(df_completa_3['Fecha_Reclamacion']-df_completa_3["FechaNacimiento"]).astype("<m8[Y]")
#ponemos todos los valores iguales o menores a 0 a -1, loq ue significa que la edad es menor a un año
df_completa_3.loc[df_completa_3["Edad"]<=0,"Edad"]=-1
#pasamos diccionario reg a object
df_reg["Regional_Id"]=df_reg["Regional_Id"].astype("int")
#para faciliar analisis grafico, se crea base de datos donde se incorporan los significados de los diagnosticos, reclamaciones, sexo y regional
remp1=dict(zip(df_diag['Diagnostico_Codigo'],df_diag["Diagnostico_Desc"]))
remp2=dict(zip(df_gen['Sexo_Cd'],df_gen["Sexo_Cd.1"]))
remp3=dict(zip(df_reg['Regional_Id'],df_reg["Regional_desc"]))
remp4=dict(zip(df_recl['Reclamacion_Cd'],df_recl["Reclamacion_Desc"]))
df_completa_3["Diagnostico_Codigo"]=df_completa_3["Diagnostico_Codigo"].replace(remp1)
df_completa_3["Sexo_Cd"]=df_completa_3["Sexo_Cd"].replace(remp2)
df_completa_3["Regional"]=df_completa_3["Regional"].replace(remp3)
df_completa_3["Reclamacion_Cd"]=df_completa_3["Reclamacion_Cd"].replace(remp4)
pd.set_option('display.max_colwidth', None)
df_completa_3["Cod_Diagnostico"]=df_completa_2["Diagnostico_Codigo"]
df_completa_3["Cod_Reclamacion"]=df_completa_2["Reclamacion_Cd"]
df_completa_3
| Fecha_Reclamacion | Afiliado_Id | Reclamacion_Cd | Diagnostico_Codigo | Numero_Utilizaciones | Valor_Utilizaciones | Sexo_Cd | FechaNacimiento | Regional | CANCER | EPOC | DIABETES | HIPERTENSION | ENF_CARDIOVASCULAR | mes_rec | año_rec | mes_nac | Edad | Cod_Diagnostico | Cod_Reclamacion | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 2019-10-28 | 7567894 | EXAMENES DE DIAGNOSTICO | TRASTORNO DE LA MAMA, NO ESPECIFICADO | 1 | 139376 | F | 1979-05-10 | REGIONAL NORTE | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 10 | 2019 | 5 | 40.0 | N649 | R14 |
| 1 | 2019-12-23 | 12170310 | EXAMENES DE DIAGNOSTICO | DOLOR, NO ESPECIFICADO | 1 | 135179 | F | 1979-04-14 | REGIONAL NORTE | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 12 | 2019 | 4 | 40.0 | R529 | R14 |
| 2 | 2019-12-09 | 4512914 | EXAMENES DE DIAGNOSTICO | OTROS CONTROLES GENERALES DE SALUD DE RUTINA DE OTRAS SUBPOBLACIONES DEFINIDAS | 1 | 61854 | F | 1952-10-26 | REGIONAL OCCIDENTE | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 12 | 2019 | 10 | 67.0 | Z108 | R14 |
| 3 | 2019-08-17 | 3212499 | EXAMENES DE DIAGNOSTICO | DOLOR PRECORDIAL | 1 | 182900 | M | 1965-10-03 | REGIONAL OCCIDENTE | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 8 | 2019 | 10 | 53.0 | R072 | R14 |
| 4 | 2019-12-10 | 9055837 | TRATAMIENTO MEDICO AMBULATORIO POR ACCIDENTES | ESGUINCES Y TORCEDURAS DEL TOBILLO | 1 | 122053 | F | 1972-04-29 | REGIONAL OCCIDENTE | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 12 | 2019 | 4 | 47.0 | S934 | R25 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 100673 | 2019-10-25 | 29436599 | EXAMENES DE DIAGNOSTICO | EMBARAZO CONFIRMADO | 1 | 63240 | F | 1988-03-27 | REGIONAL CENTRO | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 10 | 2019 | 3 | 31.0 | Z321 | R14 |
| 100674 | 2019-11-09 | 1304923 | EXAMENES DE DIAGNOSTICO | INFECCIÓN DE VÍAS URINARIAS, SITIO NO ESPECIFICADO | 1 | 994034 | F | 1930-01-06 | REGIONAL OCCIDENTE | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 11 | 2019 | 1 | 89.0 | N390 | R14 |
| 100675 | 2019-12-04 | 13172140 | EXAMENES DE DIAGNOSTICO | HIPERTENSIÓN ESENCIAL (PRIMARIA) | 1 | 256556 | F | 1958-09-11 | REGIONAL NORTE | 0.0 | 0.0 | 1.0 | 1.0 | 0.0 | 12 | 2019 | 9 | 61.0 | I10X | R14 |
| 100676 | 2019-04-30 | 47260743 | TRASLADO EN AMBULANCIA | CEFALEA | 1 | 157370 | F | 2011-03-21 | REGIONAL OCCIDENTE | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 4 | 2019 | 3 | 8.0 | R51X | R22 |
| 100677 | 2019-12-16 | 15535648 | CIRUGIA AMBULATORIA POR ACCIDENTE | TRAUMATISMO POR APLASTAMIENTO DE DEDO(S) DEL PIE | 1 | 111147 | F | 1989-06-15 | REGIONAL NORTE | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 12 | 2019 | 6 | 30.0 | S971 | R4 |
100673 rows × 20 columns
df_completa_3['Edad'].plot(kind='hist', bins=20, title='Reclamaciones por Edad')
plt.gca().spines[['top', 'right',]].set_visible(False)
df_completa_3.groupby('Regional').size().plot(kind='barh', color=sns.palettes.mpl_palette('Dark2'),title='Reclamaciones por Region')
plt.gca().spines[['top', 'right',]].set_visible(False)
df_completa_3.groupby('Sexo_Cd').size().plot(kind='barh', color=sns.palettes.mpl_palette('Dark2'),title='Reclamaciones por Genero')
plt.gca().spines[['top', 'right',]].set_visible(False)
print("Reclamaciones por genero (%): \n",((df_completa_3["Sexo_Cd"].value_counts()/len(df_completa_3))*100).round(2))
Reclamaciones por genero (%): F 62.01 M 37.99 Name: Sexo_Cd, dtype: float64
El 62% de las reclamaciones son hechas por mujeres
df_completa_3['Numero_Utilizaciones'].plot(kind='hist', bins=20, title='Numero_Utilizaciones')
plt.gca().spines[['top', 'right',]].set_visible(False)
print("Numero_Utilizaciones: \n",df_completa_3["Numero_Utilizaciones"].value_counts())
Numero_Utilizaciones: 1 98323 2 2205 3 133 4 10 5 2 Name: Numero_Utilizaciones, dtype: int64
La mayoria de reclamaciones tienen una sola utilizacion.
def _plot_series(series, series_name, series_index=0):
from matplotlib import pyplot as plt
import seaborn as sns
palette = list(sns.palettes.mpl_palette('Dark2'))
xs = series['Fecha_Reclamacion']
ys = series['Valor_Utilizaciones']
plt.plot(xs, ys, label=series_name, color=palette[series_index % len(palette)])
fig, ax = plt.subplots(figsize=(10, 5.2), layout='constrained')
df_sorted = df_completa_3.sort_values('Fecha_Reclamacion', ascending=True)
_plot_series(df_sorted, '')
sns.despine(fig=fig, ax=ax)
plt.xlabel('Fecha_Reclamacion')
_ = plt.ylabel('Valor_Utilizaciones')
vemos como los reclamos se han hecho en su mayoria despues de 2018 y en general tienen una tendencia a subir su valor en sus valores mas altos o atipicos.
# --- Reporte exploratorio del dataset ---
ProfileReport(df_completa_3, title='Reporte exploratorio del dataset final', minimal=True,
progress_bar=False, interactions=None, explorative=True, dark_mode=True,
notebook={'iframe':{'height': '600px'}}, html={'style':{'primary_color': '#FFCC00'}},
missing_diagrams={'heatmap': False, 'dendrogram': False}).to_notebook_iframe()
Conclusiones del reporte:
#Se procede a generar base de datos para utilizacion en el modelo
df_completa_modelo=df_completa_2.drop(columns=["Fecha_Reclamacion","Afiliado_Id","FechaNacimiento"])
df_completa_modelo.head(2)
| Reclamacion_Cd | Diagnostico_Codigo | Numero_Utilizaciones | Valor_Utilizaciones | Sexo_Cd | Regional | CANCER | EPOC | DIABETES | HIPERTENSION | ENF_CARDIOVASCULAR | mes_rec | año_rec | mes_nac | Edad | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | R14 | N649 | 1 | 139376 | 1.0 | 40 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 10 | 2019 | 5 | 40.47 |
| 1 | R14 | R529 | 1 | 135179 | 1.0 | 40 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 12 | 2019 | 4 | 40.69 |
#exportar final
df_completa_modelo.to_csv("df_completa_modelo.csv",index=False)
1.descargar jpynb manualmente
2.cargar en la raiz del collab
3.ejecutar el siguiente codigo
4.descargar .HTML del entorno
%%shell
jupyter nbconvert --to html "/content/drive/MyDrive/Colab Notebooks/Analitica 3 2023-2/Módulo salud/clase 9 nov/clase 9nov.ipynb"